﻿using APILibrary.TypeDic;
using RazorEngine;
using RazorEngine.Templating;
using RazorTs.analysis;
using RazorTs.ModelInfo;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web.Http;
using TsInterfaceRazor.analysis;
using TsInterfaceRazor.ModelInfo;

namespace TsInterfaceRazor
{
    static class Program
    {


        //public enum MyTestEnum
        //{
        //    A = 0,
        //    B = 5,
        //    C = 100,
        //}
        //public enum MyTestEnum1111
        //{
        //    A = 0,
        //    B = 5,
        //    C = 100,
        //}

        static void Main(string[] args)
        {
            //AppDomain.CurrentDomain.BaseDirectory

            //Entry.Start(
            //    typeof(FinancialController), 
            //    TemplateMethod.Template, 
            //    TemplateInterface.Template,
            //    TemplateEnum.Template,
            //    AnalysisType.GenericsType,
            //    @"D:\ApiFile\api" + $"", Entry.AppendString
            //    );

            //Entry.Start(
            //   typeof(SalesOrderController),
            //   TemplateMethod.Template,
            //   TemplateInterface.Template,
            //   TemplateEnum.Template,
            //   AnalysisType.GenericsType,
            //   @"D:\ApiFile\api" + $"", Entry.AppendString
            //   );
        }






        //#region demo

        //static void GenerateFile(string path,string content)
        //{

        //    //var filePath = AppDomain.CurrentDomain.BaseDirectory + @"File\Demo.ts";

        //    //如果文本文件Demo.txt已经存在，则将其删除
        //    if (File.Exists(path))
        //    {
        //        File.Delete(path);
        //    }
        //    //else
        //    //{
        //    //    File.Create(path);
        //    //}

        //    //创建文本文件Demo.txt，并写入初始字符串"123456789"
        //    using (var fileStream = new FileStream(path, FileMode.CreateNew))
        //    {
        //        var result1 = content.Replace(";", "\r\n");
        //        //string content = "123456789";//向文本文件Demo.txt中写入的内容为"123456789"
        //        byte[] data = System.Text.Encoding.UTF8.GetBytes(result1);//使用ASCII码将字符串转换为字节数据，所以一个字符占用一个字节

        //        fileStream.Write(data, 0, data.Length);
        //    }
        //}


        ////可以实现自动生成调用api文件
        //static void Main2222(string[] args)
        //{
        //    #region Test1
        //    try
        //    {


        //        string tsTemplate = @" 
        //   @Model.ClassDescribe @(';') export    interface   @Model.ClassName { 
        //          @foreach (var item in Model.ModelPropertyDescribes)
        //          {
        //                      @item.PropertyDescribe @(';') @item.PropertyName if(@item.IsNull){@('?')}else{}  @(':') @item.PropertyType @(';') 

        //          }
        //      }
        //                                      ";
        //        //var ssss = new ModelDescribe();
        //        ////ssss.ModelPropertyDescribes = new List<ModelPropertyDescribe>();
        //        Assembly ass = Assembly.GetAssembly(typeof(ExcelController));
        //        //获取所有的类型
        //        Type[] types = ass.GetTypes();
        //        List<ApiDescribe> apisDescribe = new List<ApiDescribe>();
        //        foreach (var t in types)
        //        {
        //            var modelString =new  StringBuilder();
        //            apisDescribe = new List<ApiDescribe>();
        //            ToTs.ModelDescribes = new List<ModelDescribe>();
        //            //判断是否集成该接口
        //            if (t.GetInterface("IAPIDocument") != null)
        //            {
        //                //过滤方法
        //                foreach (var item in t.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Static))
        //                {
        //                    ApiDescribe apiDescribe = new ApiDescribe();

        //                    var isPost = item.GetCustomAttribute(typeof(HttpPostAttribute));
        //                    var isGet = item.GetCustomAttribute(typeof(HttpGetAttribute));

        //                    apiDescribe.MethodName = item.Name;
        //                    apiDescribe.Describe = ToTs.GetDescribe(item.GetType());
        //                    bool isT = false;
        //                    //判断是否是带谓词的方法
        //                    if (isPost != null)
        //                    {
        //                        var name=AnalysisType.GetMethodReturn(item.ReturnType);
        //                        Console.WriteLine("返回值" + name);
        //                        var sRetrun = item.ReturnType.Name;
        //                        if (item.ReturnType.IsGenericType)
        //                        {
        //                            sRetrun = sRetrun.Replace("`1", "");
        //                            if (sRetrun == "Task")
        //                            {
        //                                sRetrun = item.ReturnType.GetGenericArguments()[0].Name;
        //                                if (sRetrun == "String")
        //                                {
        //                                    sRetrun = TypeDic.TsTypeDic[sRetrun];
        //                                }
        //                            }
        //                            if (sRetrun == "PageList" || sRetrun == "ModelEntity" || sRetrun == "ListEntity")
        //                            {
        //                                isT = true;
        //                                sRetrun += $"<{item.ReturnType.GetGenericArguments()[0].Name}>";
        //                            }
        //                        }
                                
        //                        else
        //                        {
        //                            if (sRetrun == "String")
        //                            {
        //                                sRetrun = TypeDic.TsTypeDic[sRetrun];
        //                            }
        //                        }




        //                        apiDescribe.ApiUrl = $"/api/{t.Name.Replace("Controller", "")}/{item.Name}";
        //                        apiDescribe.ReturnValue = sRetrun;
        //                        apiDescribe.RequestMethod = "post";
        //                        var parameters= item.GetParameters();

        //                        ModelPropertyDescribe modelPropertyDescribe = new ModelPropertyDescribe();

        //                        foreach (var parameter in parameters)
        //                        {
        //                            //modelPropertyDescribe.PropertyName = parameter.Name;
        //                            //modelPropertyDescribe.PropertyType = parameter.ParameterType.Name;
        //                            //modelPropertyDescribe.PropertyDescribe= ToTs.GetDescribe(parameter.ParameterType);
        //                            //apiDescribe.ModelPropertyParameterDescribes.Add(modelPropertyDescribe);
        //                            //var isResult= ToTs.GetModelDescribes(parameter.ParameterType);
        //                            var isData = parameter.GetCustomAttribute(typeof(FromBodyAttribute));
        //                            if (isData != null)
        //                            {
        //                                modelPropertyDescribe.PropertyName = parameter.Name;
        //                                modelPropertyDescribe.PropertyType = parameter.ParameterType.Name;
        //                                modelPropertyDescribe.PropertyDescribe = ToTs.GetDescribe(parameter.ParameterType);
        //                                apiDescribe.ModelPropertyParameterDescribes.Add(modelPropertyDescribe);
        //                                var isResult = ToTs.GetModelDescribes(parameter.ParameterType);
        //                                apiDescribe.IsParams = false;
        //                                apiDescribe.IsData = true;
        //                            }
        //                            else
        //                            {
        //                                modelPropertyDescribe.PropertyName = parameter.Name;
        //                                modelPropertyDescribe.PropertyType = TypeDic.TsTypeDic[parameter.ParameterType.Name];
        //                                modelPropertyDescribe.PropertyDescribe = ToTs.GetDescribe(parameter.ParameterType);
        //                                apiDescribe.ModelPropertyParameterDescribes.Add(modelPropertyDescribe);
        //                            }
        //                        }
                               
        //                    }

        //                    if (isGet != null)
        //                    {
        //                        var name = AnalysisType.GetMethodReturn(item.ReturnType);
        //                        Console.WriteLine("返回值"+name);
        //                        var sRetrun = item.ReturnType.Name;
        //                        if (item.ReturnType.IsGenericType)
        //                        {
        //                            sRetrun = sRetrun.Replace("`1", "");
        //                            if (sRetrun == "PageList" || sRetrun == "ModelEntity" || sRetrun == "ListEntity")
        //                            {
        //                                isT = true;
        //                                sRetrun += $"<{item.ReturnType.GetGenericArguments()[0].Name}>";
        //                            }
        //                        }
                               
        //                        else
        //                        {
        //                            if (sRetrun == "String")
        //                            {
        //                                sRetrun = TypeDic.TsTypeDic[sRetrun];
        //                            }
        //                        }
        //                        apiDescribe.ApiUrl = $"/api/{t.Name.Replace("Controller","")}/{item.Name}";
        //                        apiDescribe.ReturnValue = sRetrun;
        //                        apiDescribe.RequestMethod = "get";
        //                        var parameters = item.GetParameters();
        //                        List<ModelPropertyDescribe> modelPropertyDescribes = new List<ModelPropertyDescribe>();
        //                        //ModelPropertyDescribe modelPropertyDescribe = new ModelPropertyDescribe();

        //                        foreach (var parameter in parameters)
        //                        {
        //                            ModelPropertyDescribe modelPropertyDescribe = new ModelPropertyDescribe();
        //                            var abs = ToTs.GetDescribe(parameter);
        //                            var isData = parameter.GetCustomAttribute(typeof(FromBodyAttribute));
        //                            if (isData != null)
        //                            {
        //                                modelPropertyDescribe.PropertyName = parameter.Name;
        //                                modelPropertyDescribe.PropertyType = parameter.ParameterType.Name;
        //                                modelPropertyDescribe.PropertyDescribe = ToTs.GetDescribe(parameter.ParameterType);
        //                                //apiDescribe.ModelPropertyParameterDescribes.Add(modelPropertyDescribe);
        //                                var isResult = ToTs.GetModelDescribes(parameter.ParameterType);
        //                                apiDescribe.IsParams = false;
        //                                apiDescribe.IsData = true;
        //                            }
        //                            else
        //                            {

        //                                if (parameter.ParameterType.IsIEnumerableType())
        //                                {//是否是IsIEnumerableType

        //                                    var rootType = parameter.ParameterType.GetGenericArguments()[0];

        //                                    if (rootType.IsClass && rootType.Name != "String")
        //                                    {//如果是类的话
        //                                        modelPropertyDescribe.PropertyType += "Array<";
        //                                        modelPropertyDescribe.PropertyType += rootType.Name;
        //                                        modelPropertyDescribe.PropertyType += ">";
        //                                    }
        //                                    else
        //                                    {
        //                                        if (rootType.IsNullableType())
        //                                        {
        //                                            var rootType2 = rootType.GetGenericArguments()[0];
        //                                            modelPropertyDescribe.PropertyType += "Array<";
        //                                            modelPropertyDescribe.PropertyType += APILibrary.TypeDic.TypeDic.TsTypeDic[rootType2.ToString().Split('.')[rootType2.ToString().Split('.').Length - 1]];
        //                                            //modelPropertyDescribe.PropertyType += "| null";
        //                                            modelPropertyDescribe.IsNull = true;
        //                                            modelPropertyDescribe.PropertyType += ">";
        //                                        }
        //                                        else
        //                                        {
        //                                            modelPropertyDescribe.PropertyType += "Array<";
        //                                            modelPropertyDescribe.PropertyType += APILibrary.TypeDic.TypeDic.TsTypeDic[rootType.ToString().Split('.')[rootType.ToString().Split('.').Length - 1]];
        //                                            modelPropertyDescribe.PropertyType += ">";
        //                                            //if (k.IsNullableType())
        //                                            //{
        //                                            //    modelPropertyDescribe.PropertyType += "|| null";
        //                                            //}
        //                                        }
        //                                    }


        //                                }
        //                                else
        //                                {
        //                                    if (parameter.ParameterType.IsNullableType())
        //                                    {
        //                                        var rootType = parameter.ParameterType.GetGenericArguments()[0];
        //                                        modelPropertyDescribe.PropertyType = APILibrary.TypeDic.TypeDic.TsTypeDic[rootType.ToString().Split('.')[rootType.ToString().Split('.').Length - 1]];
        //                                        //modelPropertyDescribe.PropertyType += "| null";
        //                                        modelPropertyDescribe.IsNull = true;
        //                                    }
        //                                    else
        //                                    {
        //                                        modelPropertyDescribe.PropertyType = APILibrary.TypeDic.TypeDic.TsTypeDic[parameter.ParameterType.Name.ToString().Split('.')[parameter.ParameterType.Name.ToString().Split('.').Length - 1]];
        //                                        //if (k.IsNullableType())
        //                                        //{
        //                                        //    modelPropertyDescribe.PropertyType += "|| null";
        //                                        //}
        //                                    }
        //                                }


                                      
        //                                modelPropertyDescribe.PropertyName = parameter.Name;
        //                                //modelPropertyDescribe.PropertyType = TypeDic.TsTypeDic[parameter.ParameterType.Name];
        //                                modelPropertyDescribe.PropertyDescribe = ToTs.GetDescribe(parameter);
        //                                //apiDescribe.ModelPropertyParameterDescribes.Add(modelPropertyDescribe);
        //                            }
        //                            modelPropertyDescribes.Add(modelPropertyDescribe);

        //                        }
        //                        apiDescribe.ModelPropertyParameterDescribes = modelPropertyDescribes;
        //                    }
        //                    var s = item.ReturnParameter;
        //                    apisDescribe.Add(apiDescribe);
        //                    if (isT)
        //                    {
        //                        var result=AnalysisType.Start(item.ReturnType.GetGenericArguments()[0]);
        //                        if (result.TypeEnum != TypeEnum.BaseType)
        //                        {
        //                            var result111 = ToTs.GetModelDescribes(item.ReturnType.GetGenericArguments()[0]);
        //                        }
        //                    }
        //                    else
        //                    {
                              
        //                        var result111 = ToTs.GetModelDescribes(item.ReturnType);
        //                    }
        //                    //var s = item.ReturnParameter;
        //                    //apisDescribe.Add(apiDescribe);
        //                    //var result111 = ToTs.GetModelDescribes(s.ParameterType);
        //                    //if (result111)
        //                    //{
        //                    //    //ToTs.ModelDescribes.ForEach(e => { Console.WriteLine(e.ClassName); });

                              
        //                    //    //ToTs.ModelDescribes = new List<ModelDescribe>();
        //                    //}
        //                }


        //                ToTs.ModelDescribes=ToTs.ModelDescribes.GroupBy(e=>e.ClassName).Select(d=>d.FirstOrDefault()).ToList();

        //                foreach (var item1111 in ToTs.ModelDescribes)
        //                {
        //                    var result1 = Engine.Razor.RunCompile(tsTemplate, "templateKey", null, item1111);
        //                    //Console.WriteLine(result);
        //                    result1 = result1.Replace("&lt;", "<");
        //                    result1 = result1.Replace("&gt;", ">");
        //                    Console.WriteLine(result1);
        //                    modelString.Append(result1);
        //                    //GenerateFile(AppDomain.CurrentDomain.BaseDirectory + $"File\\{item1111.ClassName}.ts", result1.Trim());
        //                }
        //                var describes = new StringBuilder();
        //                describes.Append("/**");
                    
        //                foreach (var item in apisDescribe)
        //                {
        //                    describes.Append($"* {item.Describe}");

        //                var sss = "";
        //                    int i = 0;
        //                    var s = new StringBuilder();
        //                    var ss = new StringBuilder();
        //                    ss.Append("{");
        //                    foreach (var item3 in item.ModelPropertyParameterDescribes)
        //                    {
        //                        describes.Append($"* @param {item3.PropertyName} {item3.PropertyDescribe}");
        //                        s.Append(item3.PropertyName + (item3.IsNull?"?":"") +":" + item3.PropertyType + ",");
        //                        ss.Append(item3.PropertyName + ":" + item3.PropertyName + ",");
        //                        if (i == 0)
        //                        {
        //                            sss = item3.PropertyName;
        //                        }
        //                    }
        //                    if (item.ModelPropertyParameterDescribes.Count() >0){
        //                        s.Remove(s.Length - 1, 1);
        //                        ss.Remove(ss.Length - 1, 1);
        //                        ss.Append("}");
        //                        item.ParameterString = s.ToString();
        //                        item.Params = ss.ToString();
        //                        if (item.IsData)
        //                        {
        //                            item.Data = sss;
        //                        }
        //                    }
                           
        //                    describes.Append($" * @returns");
        //                    describes.Append($" */");
        //                    item.Describes = describes.ToString();
        //                }
                       

        //                var resultString =
        //           Engine.Razor.RunCompile(RazorTs.TemplateAxios.TemplateMethod.Template, "templateKey222", null, apisDescribe);
        //                resultString = resultString.Replace("&lt;", "<");
        //                resultString = resultString.Replace("&gt;", ">");
        //                GenerateFile(AppDomain.CurrentDomain.BaseDirectory + $"File\\{t.Name}.ts", resultString + modelString);
        //                Console.WriteLine(resultString);
        //            }


                  

        //        }


        //        Console.WriteLine();

        //    }
        //    catch (Exception ex)
        //    {
        //        Console.WriteLine(ex.ToString());
        //        throw;
        //    }
        //    #endregion
        //}



        //static void Main111(string[] args)
        //{
        //    //PageList<SealsregisterModel> page = new PageList<SealsregisterModel>();



        //    GetType(typeof(PageList<SealsregisterModel>));

        //}
        //public static List<ModelDescribe> ModelDescribes = new List<ModelDescribe>();
        //public static List<string> ClassNames = new List<string>();
        //private static ModelPropertyDescribe GetType(Type type)
        //{
        //    ModelPropertyDescribe modelProperty = new ModelPropertyDescribe();
        //    ModelDescribe modelDescribe = new ModelDescribe();
        //    List<ModelPropertyDescribe> modelPropertyDescribes = new List<ModelPropertyDescribe>();
        //    var sss = AnalysisType.Start(type);
        //    switch (sss.TypeEnum)
        //    {
        //        case TypeEnum.Class:
        //            modelDescribe.ClassName = type.Name;
        //            modelDescribe.ClassDescribe= ToTs.GetDescribe(type);
        //            ClassNames.Add(modelDescribe.ClassName);
        //            ModelPropertyDescribe modelPropertyDescribe = new ModelPropertyDescribe();
        //            foreach (var item in type.GetProperties())
        //            {
        //                modelPropertyDescribe.PropertyName = item.Name;
        //                modelPropertyDescribe.PropertyDescribe = ToTs.GetDescribe(item);
        //                var result= GetType(item.PropertyType);
        //                modelPropertyDescribe.PropertyType= result.PropertyType;
        //                modelProperty.IsNull= result.IsNull;
        //                modelPropertyDescribes.Add(modelPropertyDescribe);
        //            }
        //            break;
        //        case TypeEnum.BaseType:
        //            modelProperty.PropertyType = TypeDic.TsTypeDic[type.Name];
        //            return modelProperty;
        //        case TypeEnum.IEnumerable:
        //            break;
        //        case TypeEnum.IsArray:
        //            break;
        //        case TypeEnum.Generic:
                    
        //            foreach (var item in type.GetGenericArguments())
        //            {
        //                if (type.IsNullableType())
        //                {
        //                    modelProperty.IsNull = true;

        //                }
        //                //else
        //                //{

        //                //}
        //                var s=GetType(item);
        //                return s;
        //                //Console.WriteLine(s);
        //            }
        //            break;
        //        case TypeEnum.Enum:
        //            break;
        //        case TypeEnum.Other:
        //            break;
        //        default:
        //            break;
        //    }

        //    return modelProperty;
        //}

        //public static IEnumerable<TSource> Distinct11<TSource, TKey>(
        //this IEnumerable<TSource> source,
        //Func<TSource, TKey> keySelector)
        //{
        //    var hashSet = new HashSet<TKey>();

        //    foreach (TSource element in source)
        //    {
        //        if (hashSet.Add(keySelector(element)))
        //        {
        //            yield return element;
        //        }
        //    }
        //}
        //public static bool IsEnumerable(PropertyInfo propertyInfo)
        //{
        //    var propType = propertyInfo.PropertyType;
        //    //x => x.IsGenericType &&
        //    var ienumerableInterfaces = propType.GetInterfaces()
        //      .Where(x =>  x.GetGenericTypeDefinition() ==
        //         typeof(IEnumerable<>)).ToList();

        //    if (ienumerableInterfaces.Count == 0) return false;

        //    return ienumerableInterfaces.All(x =>
        //       x.GenericTypeArguments[0] != typeof(string) &&
        //       !x.GenericTypeArguments[0].IsValueType);
        //}
        //public static bool IsEnumerable(Type propertyInfo)
        //{
        //    //x.IsGenericType && 
        //    var s = propertyInfo.GetInterfaces().Where(e => e.IsGenericType).ToList();
        //    var ienumerableInterfaces = propertyInfo.GetInterfaces().Where(e => { Console.WriteLine(e.GetGenericTypeDefinition()); return true; })
        //      .Where(x =>  x.GetGenericTypeDefinition() ==
        //         typeof(IEnumerable<>)).ToList();

        //    if (ienumerableInterfaces.Count == 0) return false;

        //    return ienumerableInterfaces.All(x =>
        //       x.GenericTypeArguments[0] != typeof(string) &&
        //       !x.GenericTypeArguments[0].IsValueType);
        //}

        //#endregion
    }

    public class TestDemo
    {
        private string name;
        public int Age { get => age; set => age = value; }
        public string Name { get => name; set => name = value; }

        private int age;
    }
}
